﻿using CodeGenerator.CodeGenBL;
using CodeGenerator.Models;
using CodeGenerator.ProjectBL;
using CodeGenerator.Template;
using CodeGenerator.Util;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//using CodeGenerator.Models.DAL;

namespace CodeGenerator.Generator
{
    public class DALGenerator : GenerateBase
    {
        public DALGenerator(IProjectBL projectBL, ICodeGenBL codeGenBL, String outputPath)
            : base(projectBL, codeGenBL, outputPath)
        {
            OutputPath = outputPath;
        }

        public override void Generate(int projectId)
        {

            var classDto = this.CodeGenBL.GetClassByProjectId(new CodeGenBL.ProjectPkDto { ProjectId = projectId });
            var projectDto = this.ProjectBL.GetProject(new ProjectBL.ProjectPkDto { ProjectId = projectId });

            if (projectDto.Status && classDto.Status)
            {
                if (projectDto.Data != null && classDto.Data != null)
                {
                    ProjectModel projectModel = new ProjectModel(projectDto.Data);
                    List<ClassModel> classModel = new List<ClassModel>();

                    foreach (var dto in classDto.Data)
                    {
                        classModel.Add(new ClassModel(dto));
                    }

                    MetaData modelForDAL = new MetaData();
                    modelForDAL.Models = classModel;
                    modelForDAL.Project = projectModel;

                    List<LookupClassModel> LookupClass = new List<LookupClassModel>();
                    foreach (var myClass in modelForDAL.Models)
                    {
                        foreach (var myAttr in myClass._attributes)
                        {
                            if (myAttr.DataType.Name == "Lookup Table")
                            {
                                var lookupDto = this.CodeGenBL.GetLookupClass(new CodeGenBL.AttributePkDto { Id = myAttr.Id });
                                if (lookupDto.Data != null)
                                {
                                    LookupClass.Add(new LookupClassModel(lookupDto.Data));

                                }
                            }
                        }
                    }

                    OutputPath = Path.Combine(OutputPath, modelForDAL.Project.ProjectName);
                    DirectoryExt.CreateIfMissing(OutputPath);
                    
					GenerateDal(modelForDAL);
                    GenerateEntities(modelForDAL, LookupClass);
                    GenerateModel(modelForDAL);
                    GenerateProperties(modelForDAL);
                }

            }
        }
        
        private void GenerateDal(MetaData data)
        {
            var ttFiles = Directory.GetFiles("Template/DAL/Dal/", "*.tt", SearchOption.TopDirectoryOnly);
            var dtoPath = OutputPath + @"/{ProjectName}.DAL/Dal/";
            
			foreach (var filepath in ttFiles)
            {
                var filename = Path.GetFileNameWithoutExtension(filepath);
                foreach (var modelItem in data.Models)
                {
                    //Generate in Dto Folder
                    var destinationPath = dtoPath.Replace("{ProjectName}", data.Project.ProjectName);
                    DirectoryExt.CreateIfMissing(destinationPath);
                    var dto = (ITemplate)Activator.CreateInstance(Type.GetType("CodeGenerator.Template.DAL.Dal." + filename));
                    dto.Data.Models = new List<ClassModel> { modelItem };
                    dto.Data.Project = data.Project;
                    var filenameApplyFormat = dto.Filename.Replace("{ClassName}", modelItem.Name).Replace("{ProjectName}", data.Project.ProjectName);
                    var outputString = dto.TransformText();
                    var destinationFilePath = destinationPath + "/" + filenameApplyFormat;
                    if (File.Exists(destinationFilePath))
                    {
                        File.Delete(destinationFilePath);
                    }

                    File.WriteAllText(destinationFilePath, outputString, Encoding.GetEncoding("UTF-8"));
                }
            }
        }

        private void GenerateEntities(MetaData data, List<LookupClassModel> LookupClass)
        {
            //throw new NotImplementedException();
            
            var ttFiles = Directory.GetFiles("Template/DAL/Entities/", "*.tt", SearchOption.TopDirectoryOnly);
            var dtoPath = OutputPath + @"/{ProjectName}.DAL/Entities/";
            foreach (var filepath in ttFiles)
            {
                var filename = Path.GetFileNameWithoutExtension(filepath);
                foreach (var modelItem in data.Models)
                {
                    //Generate in Dto Folder
                    var destinationPath = dtoPath.Replace("{ProjectName}", data.Project.ProjectName);
                    DirectoryExt.CreateIfMissing(destinationPath);
                    var dto = (ITemplate)Activator.CreateInstance(Type.GetType("CodeGenerator.Template.DAL.Entities." + filename));
                    dto.Data.Models = new List<ClassModel> { modelItem };
                    dto.Data.Project = data.Project;
                    dto.lookups = LookupClass;
                    var filenameApplyFormat = dto.Filename.Replace("{ClassName}", modelItem.Name).Replace("{ProjectName}", data.Project.ProjectName);
                    var outputString = dto.TransformText();
                    var destinationFilePath = destinationPath + "/" + filenameApplyFormat;
                    if (File.Exists(destinationFilePath))
                    {
                        File.Delete(destinationFilePath);
                    }

                    File.WriteAllText(destinationFilePath, outputString, Encoding.GetEncoding("UTF-8"));
                }
            }
        }
        

        private void GenerateModel(MetaData data)
        {
            //throw new NotImplementedException();
           
            var ttFiles = Directory.GetFiles("Template/DAL/Models/", "*.tt", SearchOption.TopDirectoryOnly);
            var dtoPath = OutputPath + @"/{ProjectName}.DAL/Models";
            foreach (var filepath in ttFiles)
            {
                var filename = Path.GetFileNameWithoutExtension(filepath);
                foreach (var modelItem in data.Models)
                {
                    //Generate in Dto Folder
                    var destinationPath = dtoPath.Replace("{ProjectName}", data.Project.ProjectName).Replace("{ClassName}", modelItem.Name);
                    DirectoryExt.CreateIfMissing(destinationPath);
                    var dto = (ITemplate)Activator.CreateInstance(Type.GetType("CodeGenerator.Template.DAL.Models." + filename));
                    dto.Data.Models = new List<ClassModel>{ modelItem };
                    dto.Data.Project = data.Project;
                    var filenameApplyFormat = dto.Filename.Replace("{ClassName}", modelItem.Name).Replace("{ProjectName}", data.Project.ProjectName);
                    var outputString = dto.TransformText();
                    var destinationFilePath = destinationPath + "/" + filenameApplyFormat;
                    if (File.Exists(destinationFilePath))
                    {
                        File.Delete(destinationFilePath);
                    }

                    File.WriteAllText(destinationFilePath, outputString, Encoding.GetEncoding("UTF-8"));
                }
            }
        }

        private void GenerateProperties(MetaData data)
        {
            //throw new NotImplementedException();
            
            var ttFiles = Directory.GetFiles("Template/DAL/Properties/", "*.tt", SearchOption.TopDirectoryOnly);
            var dtoPath = OutputPath + @"/{ProjectName}.DAL/Properties/";
            foreach (var filepath in ttFiles)
            {
                var filename = Path.GetFileNameWithoutExtension(filepath);
                foreach (var modelItem in data.Models)
                {
                    //Generate in Dto Folder
                    var destinationPath = dtoPath.Replace("{ProjectName}", data.Project.ProjectName);
                    DirectoryExt.CreateIfMissing(destinationPath);
                    var dto = (ITemplate)Activator.CreateInstance(Type.GetType("CodeGenerator.Template.DAL.Properties." + filename));
                    dto.Data.Models = new List<ClassModel>{modelItem};
                    dto.Data.Project = data.Project;
                    var filenameApplyFormat = dto.Filename.Replace("{ClassName}", modelItem.Name).Replace("{ProjectName}", data.Project.ProjectName);
                    var outputString = dto.TransformText();
                    var destinationFilePath = destinationPath + "/" + filenameApplyFormat;
                    if (File.Exists(destinationFilePath))
                    {
                        File.Delete(destinationFilePath);
                    }

                    File.WriteAllText(destinationFilePath, outputString, Encoding.GetEncoding("UTF-8"));
                }
            }
        }


        //private void GenerateDal(ModelList data)
        //{
        //    var ttFiles = Directory.GetFiles("Template/DAL/Dal/", "*.tt", SearchOption.TopDirectoryOnly);
        //    var dtoPath = OutputPath + @"/{ProjectName}.DAL/Dal/";
        //    foreach (var filepath in ttFiles)
        //    {
        //        var filename = Path.GetFileNameWithoutExtension(filepath);
        //        foreach (var modelItem in data.Models)
        //        {
        //            //Generate in Dto Folder
        //            var destinationPath = dtoPath.Replace("{ProjectName}", data.Project.ProjectName);
        //            DirectoryExt.CreateIfMissing(destinationPath);
        //            var dto = (ITemplate)Activator.CreateInstance(Type.GetType("CodeGenerator.Template.DAL.Dal." + filename));
        //            dto.Data.Models = new List<ClassModel> { modelItem };
        //            dto.Data.Project = data.Project;
        //            var filenameApplyFormat = dto.Filename.Replace("{ClassName}", modelItem.Name).Replace("{ProjectName}", data.Project.ProjectName);
        //            var outputString = dto.TransformText();
        //            var destinationFilePath = destinationPath + "/" + filenameApplyFormat;
        //            if (File.Exists(destinationFilePath))
        //            {
        //                File.Delete(destinationFilePath);
        //            }

        //            File.WriteAllText(destinationFilePath, outputString, Encoding.GetEncoding("UTF-8"));
        //        }
        //    }
        //}

        //private void GenerateEntities(ModelList data)
        //{
        //    //throw new NotImplementedException();

        //    var ttFiles = Directory.GetFiles("Template/DAL/Entities/", "*.tt", SearchOption.TopDirectoryOnly);
        //    var dtoPath = OutputPath + @"/{ProjectName}.DAL/Entities/";
        //    foreach (var filepath in ttFiles)
        //    {
        //        var filename = Path.GetFileNameWithoutExtension(filepath);
        //        foreach (var modelItem in data.Models)
        //        {
        //            //Generate in Dto Folder
        //            var destinationPath = dtoPath.Replace("{ProjectName}", data.Project.ProjectName);
        //            DirectoryExt.CreateIfMissing(destinationPath);
        //            var dto = (ITemplate)Activator.CreateInstance(Type.GetType("CodeGenerator.Template.DAL.Entities." + filename));
        //            dto.Data.Models = new List<ClassModel> { modelItem };
        //            dto.Data.Project = data.Project;
        //            var filenameApplyFormat = dto.Filename.Replace("{ClassName}", modelItem.Name).Replace("{ProjectName}", data.Project.ProjectName);
        //            var outputString = dto.TransformText();
        //            var destinationFilePath = destinationPath + "/" + filenameApplyFormat;
        //            if (File.Exists(destinationFilePath))
        //            {
        //                File.Delete(destinationFilePath);
        //            }

        //            File.WriteAllText(destinationFilePath, outputString, Encoding.GetEncoding("UTF-8"));
        //        }
        //    }
        //}


        //private void GenerateModel(ModelList data)
        //{
        //    //throw new NotImplementedException();

        //    var ttFiles = Directory.GetFiles("Template/DAL/Models/", "*.tt", SearchOption.TopDirectoryOnly);
        //    var dtoPath = OutputPath + @"/{ProjectName}.DAL/Models/{ClassName}";
        //    foreach (var filepath in ttFiles)
        //    {
        //        var filename = Path.GetFileNameWithoutExtension(filepath);
        //        foreach (var modelItem in data.Models)
        //        {
        //            //Generate in Dto Folder
        //            var destinationPath = dtoPath.Replace("{ProjectName}", data.Project.ProjectName).Replace("{ClassName}", modelItem.Name);
        //            DirectoryExt.CreateIfMissing(destinationPath);
        //            var dto = (ITemplate)Activator.CreateInstance(Type.GetType("CodeGenerator.Template.DAL.Models." + filename));
        //            dto.Data.Models = new List<ClassModel> { modelItem };
        //            dto.Data.Project = data.Project;
        //            var filenameApplyFormat = dto.Filename.Replace("{ClassName}", modelItem.Name).Replace("{ProjectName}", data.Project.ProjectName);
        //            var outputString = dto.TransformText();
        //            var destinationFilePath = destinationPath + "/" + filenameApplyFormat;
        //            if (File.Exists(destinationFilePath))
        //            {
        //                File.Delete(destinationFilePath);
        //            }

        //            File.WriteAllText(destinationFilePath, outputString, Encoding.GetEncoding("UTF-8"));
        //        }
        //    }
        //}

        //private void GenerateProperties(ModelList data)
        //{
        //    //throw new NotImplementedException();

        //    var ttFiles = Directory.GetFiles("Template/DAL/Properties/", "*.tt", SearchOption.TopDirectoryOnly);
        //    var dtoPath = OutputPath + @"/{ProjectName}.DAL/Properties/";
        //    foreach (var filepath in ttFiles)
        //    {
        //        var filename = Path.GetFileNameWithoutExtension(filepath);
        //        foreach (var modelItem in data.Models)
        //        {
        //            //Generate in Dto Folder
        //            var destinationPath = dtoPath.Replace("{ProjectName}", data.Project.ProjectName);
        //            DirectoryExt.CreateIfMissing(destinationPath);
        //            var dto = (ITemplate)Activator.CreateInstance(Type.GetType("CodeGenerator.Template.DAL.Properties." + filename));
        //            dto.Data.Models = new List<ClassModel> { modelItem };
        //            dto.Data.Project = data.Project;
        //            var filenameApplyFormat = dto.Filename.Replace("{ClassName}", modelItem.Name).Replace("{ProjectName}", data.Project.ProjectName);
        //            var outputString = dto.TransformText();
        //            var destinationFilePath = destinationPath + "/" + filenameApplyFormat;
        //            if (File.Exists(destinationFilePath))
        //            {
        //                File.Delete(destinationFilePath);
        //            }

        //            File.WriteAllText(destinationFilePath, outputString, Encoding.GetEncoding("UTF-8"));
        //        }
        //    }
        //}
    }
}
